home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / appletalk / uab.shar / abmkip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-12  |  12.2 KB  |  502 lines

  1. /*
  2.  * $Author: cck $ $Date: 88/08/28 04:40:54 $
  3.  * $Header: abkip.c,v 1.2 88/08/28 04:40:54 cck Exp $
  4.  * $Revision: 1.2 $
  5. */
  6.  
  7. /*
  8.  * abkip.c - KIP (UDP encapsulated DDP packets) network module
  9.  *
  10.  *  abkip provides the interface from DDP to the outside world as it
  11.  *  sees it.  It includes the DDP module "routeddp".
  12.  *
  13.  *  NOTE: when running KIP, no other LAP protocols are allowed
  14.  * 
  15.  *  The justification for including parts of "lap", "ddp", etc. is that
  16.  *  that we are "gatewaying" and are allowed to do funny things at the
  17.  *  boundaries
  18.  *
  19.  * AppleTalk package for UNIX (4.2 BSD).
  20.  *
  21.  * Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University 
  22.  *  in the City of New York.
  23.  *
  24.  *
  25.  * Edit History:
  26.  *
  27.  *  June 14, 1986    Schilit    Created.
  28.  *  June 18, 1986    CCKim      Chuck's handler runs protocol
  29.  *
  30.  */
  31. /*
  32.  * The following list of exported routines is provided so you'll know what
  33.  * have to be done to do another interface type (ethertalk, etc)
  34.  *
  35.  * EXPORTED ROUTINES:
  36.  *
  37.  *  OSErr GetNodeAddress(int *mynode, int *mynet)
  38.  *     Return node addresses
  39.  *  int abInit(boolean dispay_message)
  40.  *     Initialize AppleTalk
  41.  *  int abOpen(int *returnsocket, int wantsocket, struct iovec iov[], iovlen)
  42.  *     Open a DDP socket
  43.  *  int abClose(int socket)
  44.  *     Close a DDP socket
  45.  *  void abnet_cacheit(word srcNet, byte srcNode)
  46.  *     Call in DDP protocol layer to tell the lower layer that
  47.  *      the last packet that came in was from srcNet, srcNode
  48.  *  int routeddp(struct iovec *iov, int iovlen)
  49.  *     This is the DDP incursion.  With a full AppleTalk implementation,
  50.  *     this would be part of DDP (abddp2).  This routes the DDP packet:
  51.  *     normally would decide where to send and then send via lap, with KIP
  52.  *     decides where and sends via UDP.
  53.  *
  54. */
  55.  
  56. #include <stdio.h>
  57. #include <sys/time.h>
  58. #include <sys/types.h>
  59. #include <sys/socket.h>
  60. #include <sys/uio.h>
  61. #include <sys/param.h>
  62. #include <netinet/in.h>
  63. #include <netdb.h>
  64. #include <netat/appletalk.h>
  65. #include <netat/compat.h>    /* to cover difference between bsd systems */
  66.  
  67. /*
  68.  * Configuration defines
  69.  *
  70.  * NORECVMSG - no recvmsg
  71.  * NOSENDMSG - no sendmsg
  72.  * NEEDMSGHDR - no msghdr in sockets.h - define our own
  73.  *
  74. */
  75. #ifdef NORECVMSG
  76. # ifndef NEEDNETBUF
  77. #  define NEEDNETBUF
  78. # endif
  79. #endif
  80. #ifdef NOSENDMSG
  81. # ifndef NEEDNETBUF
  82. #  define NEEDNETBUF
  83. # endif
  84. #endif
  85.  
  86. /* for forwarding */
  87. /* These three define a lookaside */
  88. /* could possibly be an array */
  89. /* cf. ip_resolve */
  90. private struct in_addr ipaddr_src; /* ip address */
  91. /* ddp address */
  92. private word ddp_srcnet;    /* ddp network part */
  93. private byte ddp_srcnode;    /* ddp node part */
  94.  
  95. import struct in_addr bridge_addr; /* .. nearest known bridge */
  96.  
  97. private struct sockaddr_in from_sin; /* network struct of last packet rec. */
  98.  
  99. #define rebPort 902        /* 0x386 */
  100. word rebport;            /* used to hold swabbed rebPort */
  101.  
  102. private struct sockaddr_in abfsin; /* apple bus foreign socketaddr/internet */
  103. private int abfd;        /* apple bus socket */
  104.  
  105. import word this_net;        /* our network number */
  106. import byte this_node;        /* our node number */
  107. import word nis_net;        /* network number of our nis */
  108. import byte nis_node;        /* node number of our nis */
  109.  
  110. import int ddp_protocol();    /* DDP protocol handler */
  111. private int kip_get();
  112. export DBUG dbug;        /* debug flags */
  113.  
  114. /* BUG: bind doesn't work when lsin is on the stack! */
  115. private struct sockaddr_in lsin; /* local socketaddr/internet */
  116. private int skt2fd[ddpMaxSkt+1]; /* translate socket to file descriptor */
  117.  
  118.  
  119. private LAP laph;
  120.  
  121. /* don't really need this */
  122. #ifdef notdef
  123. private char lapdata[lapMaxData];
  124. private struct iovec lapiov[IOV_LAP_SIZE+1]; /* lap header + data */
  125. #endif
  126.  
  127. /*
  128.  * OSErr GetNodeAddress(int *myNode,*myNet)
  129.  *
  130.  * GetNodeAddress returns the net and node numbers for the current
  131.  * host.
  132.  *
  133.  * N.B. - the myNet address is in net (htons) format.
  134.  *
  135. */
  136. export OSErr
  137. GetNodeAddress(myNode,myNet)
  138. int *myNode,*myNet;
  139. {
  140.   *myNode = this_node;
  141.   *myNet = this_net;
  142.   return(noErr);               /* is ok */
  143. }
  144. struct in_addr xdesthost;
  145. /*
  146.  * initialize
  147.  *
  148. */
  149. export
  150. abInit(disp)
  151. {
  152.   int i;
  153.   extern word bridge_net;
  154.   extern byte bridge_node;
  155.  
  156.   for (i=0; i < ddpMaxSkt+1; i++) {
  157.     skt2fd[i] = -1;        /* mark all these as unused */
  158.   }
  159.  
  160.   rebport = htons(rebPort);    /* swap to netorder */
  161.   init_fdlistening();
  162.  
  163.   /* no need to bind since we don't recv on this socket, just send... */
  164.   if ((abfd = socket(AF_INET,SOCK_DGRAM,0)) < 0) {
  165.     perror("abinit");
  166.     return(abfd);
  167.   }
  168.   abfsin.sin_family = AF_INET;
  169.   abfsin.sin_addr.s_addr = INADDR_ANY;
  170.  
  171.   bridge_node = 0, bridge_net = 0;
  172.   openatalkdb("/usr/local/lib/cap/etalk.local"); /* sets up this_* */
  173.   if (disp) {
  174.       printf("abInit: [ddp: %3d.%02d, %d]",
  175.          ntohs(this_net)>>8, htons(this_net)&0xff, this_node);
  176.       if (this_net != nis_net || this_node != nis_node)
  177.     printf(", [NBP (atis) Server: %3d.%02d, %d]",
  178.            ntohs(nis_net)>>8, htons(nis_net)&0xff, nis_node);
  179.       printf(" starting\n");
  180.   }
  181.   xdesthost.s_addr = inet_addr("127.1");
  182.   if (xdesthost.s_addr == -1)
  183.     return(-1);
  184.   DDPInit();
  185. #ifdef notdef
  186.   /* nonsensical */
  187.   LAPOpenProtocol(lapDDP,ddp_protocol); /* open protocol */
  188. #endif
  189.  
  190.   return(0);
  191. }  
  192.  
  193. /*
  194.  * int abOpen(int *skt,rskt, iov, iovlen)
  195.  *
  196.  * abOpen opens the ddp socket in "skt" or if "skt" is zero allocates
  197.  * and opens a new socket.  Upon return "skt" contains the socket number
  198.  * and the returned value is >=0 if no error, < 0 if error.
  199.  *
  200.  * iov should be an array of type "struct iov" of length at least
  201.  * IOV_LAP_SIZE+1.  Levels after IOV_LAP_LVL are assume to filled.
  202.  *
  203. */
  204. int abOpen(skt,rskt, iov, iovlen)
  205. int *skt;
  206. int rskt;
  207. struct iovec *iov;
  208. int iovlen;
  209. {
  210.   int i,fd,err;
  211.   word ipskt;
  212.  
  213. #ifdef notdef
  214.     /* could check iov not null and set to lapiov if not, etc */
  215.     /* but necessary since only (likely) client is ddp */
  216.     /* note: story is different for ethertalk, etc */
  217. #endif
  218.   /* good enough for now */
  219.   if (iov == NULL || iovlen < IOV_LAP_SIZE+1 || iovlen > IOV_READ_MAX)
  220.     return(-1);
  221.  
  222.   if ((fd = socket(AF_INET,SOCK_DGRAM,0)) < 0) {
  223.     perror("abopen");
  224.     return(fd);
  225.   }
  226.   lsin.sin_family = AF_INET;
  227.   lsin.sin_addr.s_addr = INADDR_ANY;
  228.  
  229.   *skt = (rskt == 0 ? ddpWKS : rskt); /* zero rskt is free choice */
  230. /*  ipskt = ddp2ipskt(*skt);    /* translate into ip socket number */
  231.   ipskt = *skt & 0x80 ? *skt + ddpNWKSUnix : *skt + 200;
  232.   for (i=0; i < 128; i++,ipskt++,(*skt)++) {
  233.     lsin.sin_port = htons(ipskt);
  234.     if ((err = bind(fd, (caddr_t)&lsin, sizeof(lsin))) == 0)
  235.       break;
  236.     if (rskt != 0)        /* bind failed and wanted exact? */
  237.       return(err);        /* yes... */
  238.   }
  239.   if (err == 0 && i < 128) {
  240.     iov[IOV_LAP_LVL].iov_base = (caddr_t)&laph; /* remember this */
  241.     iov[IOV_LAP_LVL].iov_len = lapSize; /* and this */
  242.     fdlistener(fd, kip_get, iov, iovlen); /* remember for later */
  243.     skt2fd[*skt] = fd;        /* remember file descriptor for socket */
  244.     return(noErr);
  245.   }
  246.   perror("abopen bind");
  247.   close(fd);
  248.   return(err);
  249. }
  250.  
  251. /*
  252.  * close off socket opened by abClose
  253.  *
  254. */
  255. export int
  256. abClose(skt)
  257. int skt;
  258. {
  259.   int fd;
  260.  
  261.   if (skt < 0 || skt > ddpMaxSkt) {
  262.     fprintf(stderr,"abClose: skt out of range\n");
  263.     exit(0);
  264.   }
  265.   fd = skt2fd[skt];
  266.   if (fd < 0)
  267.     return(0);
  268.   if (close(fd) != 0)
  269.     perror("abClose");        /* some error... */
  270.   fdunlisten(fd);
  271.   skt2fd[skt] = -1;        /* mark as unused */
  272.   return(0);
  273. }
  274.  
  275. #ifdef NEEDNETBUF
  276. #ifdef NEEDMSGHDR
  277. struct msghdr {
  278.   caddr_t msg_name;        /* name to send to */
  279.   int msg_namelen;        /* size of name */
  280.   struct iovec *msg_iov;    /* io vec */
  281.   int msg_iovlen;        /* length */
  282.   int msg_accrights;        /* dummy */
  283.   int msg_accrightslen;
  284. };
  285. #endif
  286.  
  287. /* buffer larger than maximum ddp pkt by far */
  288. private char net_buffer[ddpMaxData*2];
  289.  
  290. #ifdef NOSENDMSG
  291. /*
  292.  * limited sendmsg - limits to sizeof(net_buffer)
  293.  *
  294. */
  295. sendmsg(fd, msg, flags)
  296. int fd;
  297. struct msghdr *msg;
  298. int flags;
  299. {
  300.   int err;
  301.   int i, pos, len;
  302.   struct iovec *iov;
  303.  
  304.   iov = msg->msg_iov;
  305.   for (i=0, pos=0; i < msg->msg_iovlen; i++, iov++) {
  306.     len = iov->iov_len;
  307.     if (len+pos > sizeof(net_buffer)) /* if overflow */
  308.       len = sizeof(net_buffer)-pos; /* then limit */
  309.     bcopy(iov->iov_base, net_buffer+pos, len);
  310.     pos+= len;
  311.     if (len != iov->iov_len)    /* we don't have any more space */
  312.       break;
  313.   }
  314.   len = pos;
  315.   if ((err=sendto(abfd,net_buffer,len,0,msg->msg_name,msg->msg_namelen)) < 0)
  316.     perror("abwrite");
  317.   return(err);
  318. }
  319.  
  320. #endif /* NO SENDMSG */
  321.  
  322. #ifdef NORECVMSG
  323. recvmsg(fd, msg, flags)
  324. int fd;
  325. struct msghdr *msg;
  326. int flags;
  327. {
  328.   int err;
  329.   int i, pos, len, blen;
  330.   struct iovec *iov;
  331.  
  332.   err = recvfrom(fd, net_buffer, sizeof(net_buffer), 0,
  333.          msg->msg_name, &msg->msg_namelen);
  334.   if (err < 0)
  335.     perror("abread");
  336.   for (blen=err,pos=0,i=0,iov=msg->msg_iov; i < msg->msg_iovlen; i++, iov++) {
  337.     len = min(iov->iov_len, blen);
  338.     if ((pos + len) > sizeof(net_buffer)) /* if asking for too much */
  339.       len = sizeof(net_buffer) - pos; /* then limit */
  340.     bcopy(net_buffer+pos, iov->iov_base, len);
  341.     pos += len;
  342.     blen -= len;
  343.     /* either no more room or no more data */
  344.     if (len != iov->iov_len)
  345.       break;
  346.   }
  347.   return(err);  
  348. }
  349. #endif /* NO RECVMSG */
  350. #endif
  351.  
  352. #ifdef notdef
  353. abwrite(addr, skt, iov,iovlen)
  354. struct in_addr addr;
  355. unsigned short skt;
  356. struct iovec *iov;
  357. {
  358.   struct msghdr msg;
  359.   int err;
  360.  
  361.   abfsin.sin_addr = addr;
  362.   abfsin.sin_port = skt;
  363.   msg.msg_name = (caddr_t) &abfsin;
  364.   msg.msg_namelen = sizeof(abfsin);
  365.   msg.msg_iov = iov;
  366.   msg.msg_iovlen = iovlen;
  367.   msg.msg_accrights = 0;
  368.   msg.msg_accrightslen = 0;
  369.   if ((err = sendmsg(abfd,&msg,0)) < 0)
  370.     perror("abwrite");
  371.   return(err);  
  372. }
  373. abread(fd, iov, iovlen)
  374. struct iovec *iov;
  375. {
  376.  
  377.   msg.msg_name = (caddr_t) &from_sin;
  378.   msg.msg_namelen = sizeof(from_sin);
  379.   msg.msg_iov = iov;
  380.   msg.msg_iovlen = iovlen;
  381.   msg.msg_accrights = 0;
  382.   msg.msg_accrightslen = 0;
  383.   if ((err = recvmsg(fd,&msg,0)) < 0)
  384.     perror("abread");
  385.   return(err);  
  386. }
  387.  
  388. #endif
  389.  
  390. private int
  391. kip_get(fd, iov, iovlen)
  392. int fd;
  393. struct iovec *iov;
  394. int iovlen;
  395. {
  396.   struct msghdr msg;
  397.   int len;
  398.   LAP *lap;
  399.  
  400.   msg.msg_name = (caddr_t) &from_sin;
  401.   msg.msg_namelen = sizeof(from_sin);
  402.   msg.msg_iov = iov;
  403.   msg.msg_iovlen = iovlen;
  404.   msg.msg_accrights = 0;
  405.   msg.msg_accrightslen = 0;
  406.   if ((len = recvmsg(fd,&msg,0)) < 0) {
  407.     perror("abread");
  408.     return(len);
  409.   }
  410.   if (iov->iov_len != lapSize) /* check */
  411.     return(-1);
  412.   lap = (LAP *)iov->iov_base;
  413.   switch (lap->type) {
  414.   case lapDDP:
  415.     return(ddp_protocol(iov+1, iovlen-1, len-lapSize));
  416.     break;
  417.   default:
  418.     return(-1);
  419.   }
  420.   return(-1);
  421. }
  422.  
  423. /*
  424.  * This is the DDP/UDP interface 
  425.  *
  426. */
  427.  
  428. /* srcNet and node of last incoming packet sent to DDP */
  429. /* and valid */
  430. export void
  431. abnet_cacheit(srcNet, srcNode)
  432. word srcNet;
  433. byte srcNode;
  434. {
  435.   ddp_srcnet = srcNet;        /* remember where last packet came from */
  436.   ddp_srcnode = srcNode;
  437.   ipaddr_src.s_addr = (from_sin.sin_port == rebport) ? 0 :
  438.     from_sin.sin_addr.s_addr;
  439. }
  440.  
  441. private int
  442. ip_resolve(ddpnet, ddpnode, iphost)
  443. word ddpnet;
  444. byte ddpnode;
  445. struct in_addr *iphost;
  446. {
  447.   if (ipaddr_src.s_addr != 0 && ddpnet == ddp_srcnet && ddpnode == ddp_srcnode)
  448.     iphost->s_addr = ipaddr_src.s_addr;
  449.   else
  450.     iphost->s_addr = bridge_addr.s_addr;
  451. }
  452.  
  453. private LAP lap;
  454.  
  455. export int
  456. routeddp(iov, iovlen)
  457. struct iovec *iov;
  458. int iovlen;
  459. {
  460.   struct msghdr msg;
  461.   word destskt;
  462.   struct in_addr desthost;
  463.   DDP *ddp;
  464.   int err;
  465.  
  466.   ddp = (DDP *)iov[IOV_DDP_LVL].iov_base; /* pick out ddp header */
  467.  
  468.   /* check ddp socket(s) for validity */
  469.   if ( ddp->srcSkt == 0 || ddp->srcSkt == ddpMaxSkt ||
  470.        ddp->dstSkt == 0 || ddp->dstSkt == ddpMaxSkt ||
  471.       skt2fd[ddp->srcSkt] == -1 )
  472.     return(ddpSktErr);
  473.  
  474.   /* KIP routing code */
  475.   /* establish dest socket */
  476. /*   destskt = (word)htons(ddp2ipskt(ddp->dstSkt)); */
  477.   destskt = (word)htons(ddp->dstSkt & 0x80 ? ddp->dstSkt + ddpNWKSUnix :
  478.             ddp->dstSkt + 200);
  479.   /* resolve mapping */
  480.   ip_resolve(ddp->dstNet, ddp->dstNode, &desthost);
  481.  
  482.   /* establish a dummy lap header */
  483.   lap.type = lapDDP;
  484.   lap.dst = ddp->dstNode;
  485.   lap.src = this_node;
  486.   iov[IOV_LAP_LVL].iov_base = (caddr_t) ⪅ /* LAP header */
  487.   iov[IOV_LAP_LVL].iov_len = lapSize;       /* size  */
  488.  
  489.   /* send through */
  490.   abfsin.sin_addr = xdesthost;
  491.   abfsin.sin_port = htons(903);
  492.   msg.msg_name = (caddr_t) &abfsin;
  493.   msg.msg_namelen = sizeof(abfsin);
  494.   msg.msg_iov = iov;
  495.   msg.msg_iovlen = iovlen;
  496.   msg.msg_accrights = 0;
  497.   msg.msg_accrightslen = 0;
  498.   if ((err = sendmsg(abfd,&msg,0)) < 0)
  499.     perror("abwrite");
  500.   return(err);  
  501. }
  502.